﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Threading;

namespace Rage.UI
{
    public partial class GemmingTemplates : ChildWindow
    {

        private Action<Item> armoringCallback;
        private Action<Item> barrelCallback;
        private Action<Item> hiltCallback;
        private Action<Item> modCallback;
        private Action<Item> enhancementCallback;
        private Action<Item> colorCrystalCallback;
        private Action<Item> augmentCallback;

        private bool isLoading;

        private Dictionary<string, CheckBox> templateGroupChecks;
        private Dictionary<string, StackPanel> templateItems;
        private Character character;
        public GemmingTemplates(Character c)
        {
            isLoading = true;
            character = c;
            InitializeComponent();

#if !SILVERLIGHT
            this.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
            this.WindowState = System.Windows.WindowState.Normal;
#endif

            GemmingsShownNum.Value = Properties.GeneralSettings.Default.CountGemmingsShown;

            ComparisonArmoringList.ItemModTypeSlot = CharacterSlot.Armoring;
            ComparisonArmoringList.ItemModTypeIndex = 0;
            ComparisonArmoringList.Character = c;
            ComparisonArmoringList.SelectedItemChanged += new EventHandler(ComparisonArmoringList_SelectedItemChanged);

            ComparisonBarrelList.ItemModTypeSlot = CharacterSlot.Barrel;
            ComparisonBarrelList.ItemModTypeIndex = 0;
            ComparisonBarrelList.Character = c;
            ComparisonBarrelList.SelectedItemChanged += new EventHandler(ComparisonBarrelList_SelectedItemChanged);

            ComparisonHiltList.ItemModTypeSlot = CharacterSlot.Hilt;
            ComparisonHiltList.ItemModTypeIndex = 0;
            ComparisonHiltList.Character = c;
            ComparisonHiltList.SelectedItemChanged += new EventHandler(ComparisonHiltList_SelectedItemChanged);

            ComparisonModList.ItemModTypeSlot = CharacterSlot.Mod;
            ComparisonModList.ItemModTypeIndex = 0;
            ComparisonModList.Character = c;
            ComparisonModList.SelectedItemChanged += new EventHandler(ComparisonModList_SelectedItemChanged);

            ComparisonEnhancementList.ItemModTypeSlot = CharacterSlot.Enhancement;
            ComparisonEnhancementList.ItemModTypeIndex = 0;
            ComparisonEnhancementList.Character = c;
            ComparisonEnhancementList.SelectedItemChanged += new EventHandler(ComparisonEnhancementList_SelectedItemChanged);

            ComparisonColorCrystalList.ItemModTypeSlot = CharacterSlot.ColorCrystal;
            ComparisonColorCrystalList.ItemModTypeIndex = 0;
            ComparisonColorCrystalList.Character = c;
            ComparisonColorCrystalList.SelectedItemChanged += new EventHandler(ComparisonColorCrystalList_SelectedItemChanged);

            ComparisonAugmentList.ItemModTypeSlot = CharacterSlot.Augment;
            ComparisonAugmentList.ItemModTypeIndex = 0;
            ComparisonAugmentList.Character = c;
            ComparisonAugmentList.SelectedItemChanged += new EventHandler(ComparisonAugmentList_SelectedItemChanged);

            templateItems = new Dictionary<string, StackPanel>();
            templateItems["Custom"] = CustomStack;
            templateGroupChecks = new Dictionary<string, CheckBox>();
            templateGroupChecks["Custom"] = CustomCheck;

            foreach (GemmingTemplate template in character.CurrentGemmingTemplates)
            {
                GemmingTemplateItem templateItem = new GemmingTemplateItem(this, template);
                if (!templateItems.ContainsKey(template.Group))
                {
                    Expander groupExpander = new Expander();
                    groupExpander.Foreground = new SolidColorBrush(Color.FromRgb(61,209,242));
                    groupExpander.Margin = new Thickness(2);
                    CheckBox groupCheckBox = new CheckBox();
                    groupCheckBox.Style = this.Resources["NormalDialogCheckStyle"] as Style;
                    groupCheckBox.Content = template.Group;
                    groupCheckBox.Checked += new RoutedEventHandler(groupCheckBox_Checked);
                    groupCheckBox.Indeterminate += new RoutedEventHandler(groupCheckBox_Checked);
                    groupCheckBox.Unchecked += new RoutedEventHandler(groupCheckBox_Checked);
                    templateGroupChecks[template.Group] = groupCheckBox;
                    groupExpander.Header = groupCheckBox;
                    GroupStack.Children.Add(groupExpander);

                    StackPanel stack = new StackPanel();
                    groupExpander.Content = stack;
                    templateItems[template.Group] = stack;
                }
                templateItems[template.Group].Children.Add(templateItem);
            }
            foreach (GemmingTemplate template in character.CustomGemmingTemplates)
            {
                GemmingTemplateItem templateItem = new GemmingTemplateItem(this, template);
                templateItems[template.Group].Children.Add(templateItem);
            }
            isLoading = false;
            foreach (string group in templateGroupChecks.Keys) { UpdateGroupChecked(group); }
        }

        private void ComparisonArmoringList_SelectedItemChanged(object sender, EventArgs e) { if (armoringCallback != null) armoringCallback(ComparisonArmoringList.SelectedItem); }
        private void ComparisonBarrelList_SelectedItemChanged(object sender, EventArgs e) { if (barrelCallback != null) barrelCallback(ComparisonBarrelList.SelectedItem); }
        private void ComparisonHiltList_SelectedItemChanged(object sender, EventArgs e) { if (hiltCallback != null) hiltCallback(ComparisonHiltList.SelectedItem); }
        private void ComparisonModList_SelectedItemChanged(object sender, EventArgs e) { if (modCallback != null) modCallback(ComparisonModList.SelectedItem); }
        private void ComparisonEnhancementList_SelectedItemChanged(object sender, EventArgs e) { if (enhancementCallback != null) enhancementCallback(ComparisonEnhancementList.SelectedItem); }
        private void ComparisonColorCrystalList_SelectedItemChanged(object sender, EventArgs e) { if (colorCrystalCallback != null) colorCrystalCallback(ComparisonColorCrystalList.SelectedItem); }
        private void ComparisonAugmentList_SelectedItemChanged(object sender, EventArgs e) { if (augmentCallback != null) augmentCallback(ComparisonAugmentList.SelectedItem); }

        private void DraggableBorder_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { DragMove(); } }
        private void BT_Restore_Click(object sender, RoutedEventArgs e) { WindowState = WindowState.Normal; }
        private void BT_Maximize_Click(object sender, RoutedEventArgs e) { WindowState = WindowState.Maximized; }
        private void BT_Minimize_Click(object sender, RoutedEventArgs e) { WindowState = WindowState.Minimized; }

        private static DateTime doubleClickTime;
        private void DraggableBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (doubleClickTime == null) { doubleClickTime = DateTime.Now - new TimeSpan(0, 0, 0, 1, 0); }
            if ((doubleClickTime - DateTime.Now) < new TimeSpan(0, 0, 0, 0, 500)) {
                WindowState = WindowState != WindowState.Maximized ? WindowState.Maximized : WindowState.Normal;
                e.Handled = true;
            } else {
                doubleClickTime = DateTime.Now;
            }
        }

        private void groupCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            if (!isLoading)
            {
                CheckBox check = sender as CheckBox;
                bool enabled = check.IsChecked.GetValueOrDefault();
                foreach (UIElement element in templateItems[check.Content.ToString()].Children)
                {
                    GemmingTemplateItem item = element as GemmingTemplateItem;
                    item.template.Enabled = enabled;
                }
            }
        }

        public void UpdateGroupChecked(string group)
        {
            isLoading = true;

            bool someChecked = false;
            bool allChecked = true;
            foreach (UIElement element in templateItems[group].Children)
            {
                GemmingTemplateItem item = element as GemmingTemplateItem;
                someChecked = item.template.Enabled || someChecked;
                allChecked = item.template.Enabled && allChecked;
            }
            if (allChecked) templateGroupChecks[group].IsChecked = true;
            else if (someChecked) templateGroupChecks[group].IsChecked = null;
            else templateGroupChecks[group].IsChecked = false;
            isLoading = false;
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            ItemCache.OnItemsChanged();
            this.DialogResult = true;
        }

        public void ArmoringButtonClick(Item armoring, Control relativeTo, Action<Item> callback)
        {
            armoringCallback = null;
            ComparisonArmoringList.SelectedItem = armoring;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            ArmoringPopup.VerticalOffset = offset.Y;
            ArmoringPopup.HorizontalOffset = offset.X;

            ComparisonArmoringList.Measure(App.Current.RootVisual.RenderSize);

            // this doesn't work in WPF
            // The specified Visual and this Visual do not share a common ancestor, so there is no valid transformation between the two Visuals.
#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonArmoringList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                ArmoringPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            ArmoringPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonArmoringList.IsShown = true;
            ArmoringPopup.IsOpen = true;
            ComparisonArmoringList.Focus();
            armoringCallback = callback;
        }

        public void BarrelButtonClick(Item barrel, Control relativeTo, Action<Item> callback)
        {
            barrelCallback = null;
            ComparisonBarrelList.SelectedItem = barrel;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            BarrelPopup.VerticalOffset = offset.Y;
            BarrelPopup.HorizontalOffset = offset.X;

            ComparisonBarrelList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonBarrelList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                BarrelPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            BarrelPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonBarrelList.IsShown = true;
            BarrelPopup.IsOpen = true;
            ComparisonBarrelList.Focus();
            barrelCallback = callback;
        }

        public void HiltButtonClick(Item hyd, Control relativeTo, Action<Item> callback)
        {
            hiltCallback = null;
            ComparisonHiltList.SelectedItem = hyd;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            HiltPopup.VerticalOffset = offset.Y;
            HiltPopup.HorizontalOffset = offset.X;

            ComparisonHiltList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonHiltList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                HiltPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            HiltPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonHiltList.IsShown = true;
            HiltPopup.IsOpen = true;
            ComparisonHiltList.Focus();
            hiltCallback = callback;
        }

        public void ModButtonClick(Item meta, Control relativeTo, Action<Item> callback)
        {
            modCallback = null;
            ComparisonModList.SelectedItem = meta;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            ModPopup.VerticalOffset = offset.Y;
            ModPopup.HorizontalOffset = offset.X;

            ComparisonModList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonModList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                ModPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            ModPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonModList.IsShown = true;
            ModPopup.IsOpen = true;
            ComparisonModList.Focus();
            armoringCallback = callback;
        }

        public void EnhancementButtonClick(Item meta, Control relativeTo, Action<Item> callback)
        {
            enhancementCallback = null;
            ComparisonModList.SelectedItem = meta;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            EnhancementPopup.VerticalOffset = offset.Y;
            EnhancementPopup.HorizontalOffset = offset.X;

            ComparisonEnhancementList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonEnhancementList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                EnhancementPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            EnhancementPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonEnhancementList.IsShown = true;
            EnhancementPopup.IsOpen = true;
            ComparisonEnhancementList.Focus();
            enhancementCallback = callback;
        }

        public void ColorCrystalButtonClick(Item meta, Control relativeTo, Action<Item> callback)
        {
            colorCrystalCallback = null;
            ComparisonColorCrystalList.SelectedItem = meta;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            ColorCrystalPopup.VerticalOffset = offset.Y;
            ColorCrystalPopup.HorizontalOffset = offset.X;

            ComparisonColorCrystalList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonColorCrystalList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                ColorCrystalPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            ColorCrystalPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonColorCrystalList.IsShown = true;
            ColorCrystalPopup.IsOpen = true;
            ComparisonColorCrystalList.Focus();
            colorCrystalCallback = callback;
        }

        public void AugmentButtonClick(Item meta, Control relativeTo, Action<Item> callback)
        {
            augmentCallback = null;
            ComparisonAugmentList.SelectedItem = meta;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            AugmentPopup.VerticalOffset = offset.Y;
            AugmentPopup.HorizontalOffset = offset.X;

            ComparisonAugmentList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonAugmentList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                AugmentPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            AugmentPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonAugmentList.IsShown = true;
            AugmentPopup.IsOpen = true;
            ComparisonAugmentList.Focus();
            augmentCallback = callback;
        }

        private void GemmingsShownChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Properties.GeneralSettings.Default.CountGemmingsShown = (int)e.NewValue;
            string format = "Rage will show the top {0} moddings for an item, plus any equipped or custom moddings, if not already included in the top {0}.";
            LB_GemInfo.Text = string.Format(format, Properties.GeneralSettings.Default.CountGemmingsShown);
        }

        private void AddTemplate(object sender, RoutedEventArgs e)
        {
            GemmingTemplate newTemplate = new GemmingTemplate() { Group = "Custom", Enabled = true, Model = Calculations.Instance.Name };
            character.CustomGemmingTemplates.Add(newTemplate);
            
            GemmingTemplateItem newItem = new GemmingTemplateItem(this, newTemplate);
            CustomStack.Children.Add(newItem);
            UpdateGroupChecked(newTemplate.Group);
        }

        public void RemoveTemplate(GemmingTemplateItem item)
        {
            if (item.isCustom)
            {
                CustomStack.Children.Remove(item);
                character.CustomGemmingTemplates.Remove(item.template);
                UpdateGroupChecked(item.template.Group);
            }
        }
    }
}